import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
from datetime import datetime
import seaborn as sns
from matplotlib.font_manager import FontProperties

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号


class VegetableAnalyzer:
    def __init__(self):
        self.data_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
        self.output_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "analysis_results")

        # 创建输出目录
        if not os.path.exists(self.output_dir):
            os.makedirs(self.output_dir)
        print(f"分析结果将保存到: {self.output_dir}")

    def load_data(self):
        """加载爬取的蔬菜价格数据"""
        try:
            file_path = os.path.join(self.data_dir, 'vegetable_prices.csv')
            if not os.path.exists(file_path):
                print(f"数据文件不存在: {file_path}")
                return None

            df = pd.read_csv(file_path, encoding='utf-8-sig')

            # 转换日期列
            if 'start_date' in df.columns:
                df['start_date'] = pd.to_datetime(df['start_date'], format='%Y.%m.%d', errors='coerce')
            if 'end_date' in df.columns:
                df['end_date'] = pd.to_datetime(df['end_date'], format='%Y.%m.%d', errors='coerce')

            return df
        except Exception as e:
            print(f"加载数据时出错: {e}")
            return None

    def price_trend_analysis(self, df):
        """分析蔬菜价格趋势"""
        if df is None or len(df) == 0:
            print("没有数据可分析")
            return

        # 按日期和蔬菜名称分组计算平均价格
        if 'start_date' in df.columns and 'name' in df.columns and 'price' in df.columns:
            # 使用start_date作为日期参考
            trend_df = df.groupby(['start_date', 'name'])['price'].mean().reset_index()

            # 选择数据点最多的前5种蔬菜
            top_vegetables = df['name'].value_counts().head(5).index.tolist()

            # 绘制价格趋势图
            plt.figure(figsize=(12, 8))

            for veg in top_vegetables:
                veg_data = trend_df[trend_df['name'] == veg]
                plt.plot(veg_data['start_date'], veg_data['price'], marker='o', label=veg)

            plt.title('主要蔬菜价格趋势')
            plt.xlabel('日期')
            plt.ylabel('价格 (元/斤)')
            plt.legend()
            plt.grid(True, linestyle='--', alpha=0.7)
            plt.xticks(rotation=45)
            plt.tight_layout()

            # 保存图表
            plt.savefig(os.path.join(self.output_dir, 'vegetable_price_trend.png'))
            print("价格趋势图已保存")
        else:
            print("数据格式不正确，无法进行趋势分析")

    def price_correlation_analysis(self, df):
        """分析不同蔬菜价格之间的相关性"""
        if df is None or len(df) == 0:
            print("没有数据可分析")
            return

        # 选择数据点最多的前10种蔬菜
        top_vegetables = df['name'].value_counts().head(10).index.tolist()
        filtered_df = df[df['name'].isin(top_vegetables)]

        # 透视表转换，行为日期，列为蔬菜名称，值为价格
        if 'start_date' in filtered_df.columns:
            pivot_df = filtered_df.pivot_table(
                index='start_date',
                columns='name',
                values='price',
                aggfunc='mean'
            )

            # 计算相关系数
            corr_matrix = pivot_df.corr()

            # 绘制热力图
            plt.figure(figsize=(12, 10))
            sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1, center=0)
            plt.title('蔬菜价格相关性分析')
            plt.tight_layout()

            # 保存图表
            plt.savefig(os.path.join(self.output_dir, 'vegetable_price_correlation.png'))
            print("价格相关性热力图已保存")

            # 保存相关系数矩阵
            corr_matrix.to_csv(os.path.join(self.output_dir, 'vegetable_price_correlation.csv'),
                               encoding='utf-8-sig')
        else:
            print("数据格式不正确，无法进行相关性分析")

    def price_distribution_analysis(self, df):
        """分析蔬菜价格分布"""
        if df is None or len(df) == 0:
            print("没有数据可分析")
            return

        # 选择数据点最多的前6种蔬菜
        top_vegetables = df['name'].value_counts().head(6).index.tolist()
        filtered_df = df[df['name'].isin(top_vegetables)]

        # 绘制箱线图
        plt.figure(figsize=(14, 8))
        sns.boxplot(x='name', y='price', data=filtered_df)
        plt.title('主要蔬菜价格分布')
        plt.xlabel('蔬菜名称')
        plt.ylabel('价格 (元/斤)')
        plt.xticks(rotation=45)
        plt.tight_layout()

        # 保存图表
        plt.savefig(os.path.join(self.output_dir, 'vegetable_price_distribution.png'))
        print("价格分布箱线图已保存")

        # 计算每种蔬菜的价格统计数据
        stats_df = filtered_df.groupby('name')['price'].agg([
            'count', 'mean', 'std', 'min', 'max',
            lambda x: np.percentile(x, 25),
            lambda x: np.percentile(x, 50),
            lambda x: np.percentile(x, 75)
        ]).reset_index()

        stats_df.columns = ['蔬菜名称', '数据点数', '平均价格', '标准差', '最低价格', '最高价格',
                            '25%分位数', '中位数', '75%分位数']

        # 保存统计数据
        stats_df.to_csv(os.path.join(self.output_dir, 'vegetable_price_statistics.csv'),
                        encoding='utf-8-sig', index=False)
        print("价格统计数据已保存")

    def seasonal_analysis(self, df):
        """季节性分析"""
        if df is None or len(df) == 0 or 'start_date' not in df.columns:
            print("没有适合季节性分析的数据")
            return

        # 添加月份列
        df['month'] = df['start_date'].dt.month

        # 按月份和蔬菜名称分组计算平均价格
        monthly_avg = df.groupby(['month', 'name'])['price'].mean().reset_index()

        # 选择数据点最多的前4种蔬菜
        top_vegetables = df['name'].value_counts().head(4).index.tolist()

        # 绘制季节性价格变化图
        plt.figure(figsize=(12, 8))

        for veg in top_vegetables:
            veg_data = monthly_avg[monthly_avg['name'] == veg]
            plt.plot(veg_data['month'], veg_data['price'], marker='o', label=veg)

        plt.title('蔬菜价格的季节性变化')
        plt.xlabel('月份')
        plt.ylabel('平均价格 (元/斤)')
        plt.xticks(range(1, 13))
        plt.grid(True, linestyle='--', alpha=0.7)
        plt.legend()
        plt.tight_layout()

        # 保存图表
        plt.savefig(os.path.join(self.output_dir, 'vegetable_seasonal_analysis.png'))
        print("季节性分析图已保存")

    def price_volatility_analysis(self, df):
        """价格波动性分析"""
        if df is None or len(df) == 0:
            print("没有数据可分析")
            return

        # 计算每种蔬菜的价格变异系数 (CV = 标准差/平均值)
        volatility_df = df.groupby('name').agg({
            'price': ['count', 'mean', 'std']
        }).reset_index()

        volatility_df.columns = ['name', 'count', 'mean', 'std']
        volatility_df['cv'] = volatility_df['std'] / volatility_df['mean']  # 变异系数

        # 只保留数据点数大于等于3的蔬菜
        volatility_df = volatility_df[volatility_df['count'] >= 3]

        # 按变异系数排序
        volatility_df = volatility_df.sort_values('cv', ascending=False)

        # 绘制前15种波动性最大的蔬菜
        top_volatile = volatility_df.head(15)

        plt.figure(figsize=(12, 8))
        bars = plt.bar(top_volatile['name'], top_volatile['cv'])

        # 添加数值标签
        for bar in bars:
            height = bar.get_height()
            plt.text(bar.get_x() + bar.get_width() / 2., height,
                     f'{height:.2f}',
                     ha='center', va='bottom', rotation=0)

        plt.title('蔬菜价格波动性排名 (变异系数)')
        plt.xlabel('蔬菜名称')
        plt.ylabel('变异系数 (标准差/平均值)')
        plt.xticks(rotation=45)
        plt.tight_layout()

        # 保存图表
        plt.savefig(os.path.join(self.output_dir, 'vegetable_price_volatility.png'))
        print("价格波动性分析图已保存")

        # 保存波动性数据
        volatility_df.columns = ['蔬菜名称', '数据点数', '平均价格', '标准差', '变异系数']
        volatility_df.to_csv(os.path.join(self.output_dir, 'vegetable_price_volatility.csv'),
                             encoding='utf-8-sig', index=False)
        print("价格波动性数据已保存")

    def run_analysis(self):
        """运行所有分析"""
        # 加载数据
        df = self.load_data()

        if df is not None and len(df) > 0:
            print(f"成功加载数据，共 {len(df)} 条记录")

            # 运行各种分析
            self.price_trend_analysis(df)
            self.price_correlation_analysis(df)
            self.price_distribution_analysis(df)
            self.seasonal_analysis(df)
            self.price_volatility_analysis(df)

            print("所有分析完成")
        else:
            print("无法加载数据，分析终止")


if __name__ == "__main__":
    analyzer = VegetableAnalyzer()
    analyzer.run_analysis()